{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "9ea920d8",
   "metadata": {},
   "source": [
    "运行环境：jupyter notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a37086d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import lightgbm as lgb\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import precision_score\n",
    "from sklearn.metrics import roc_auc_score\n",
    "from sklearn.metrics import roc_curve\n",
    "from sklearn.metrics import recall_score\n",
    "from sklearn.metrics import f1_score\n",
    "\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.model_selection import StratifiedKFold\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "98dbf28e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1000000, 8)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data=pd.read_csv('银行卡诈骗数据集.csv')\n",
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "9e9aa1e8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0    912597\n",
       "1.0     87403\n",
       "Name: fraud, dtype: int64"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.fraud.value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "15812ee2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(174806, 8)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "##过采样处理\n",
    "df1 = data.query('fraud == 1')\n",
    "df2 = data.query('fraud == 0').sample(len(df1),replace=True)\n",
    "data = pd.concat([df1,df2],axis=0).reset_index(drop=True)\n",
    "data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c5796b39",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0    87403\n",
       "0.0    87403\n",
       "Name: fraud, dtype: int64"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.fraud.value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "dc85153c",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = data.iloc[:,:-1]  ##特征列\n",
    "y = data.iloc[:,-1]   ##目标列\n",
    "X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2022)\n",
    "\n",
    "scale = MinMaxScaler()  ##数据归一化，提高模型预测精度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52ecae5f",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6e1da38c",
   "metadata": {},
   "outputs": [],
   "source": [
    "#LightGBM\n",
    "#更新参数\n",
    "params = {\n",
    "        'objective' : 'multiclass',\n",
    "        'num_class' : 2,\n",
    "        'num_leaves': 45, \n",
    "        'min_child_samples': 1,\n",
    "        'min_data_in_leaf': 1,\n",
    "        'max_depth': 7,\n",
    "        'learning_rate': 0.01,\n",
    "        \"min_sum_hessian_in_leaf\": 1,\n",
    "        \"boosting\": \"gbdt\",\n",
    "        \"feature_fraction\": 1.0,  \n",
    "        \"bagging_freq\": 20,\n",
    "        \"bagging_fraction\": 0.9,\n",
    "        \"bagging_seed\": 10,\n",
    "        \"lambda_l1\": 0.0,      #l1\n",
    "        'lambda_l2': 0.0,     #l2\n",
    "        \"verbosity\": -1,\n",
    "        \"nthread\": -1,                \n",
    "        \"random_state\": 1, \n",
    "        }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "325bf15e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fold n°1\n",
      "[LightGBM] [Warning] min_data_in_leaf is set=1, min_child_samples=1 will be ignored. Current value: min_data_in_leaf=1\n",
      "Training until validation scores don't improve for 500 rounds\n",
      "[100]\ttraining's multi_logloss: 0.203313\tvalid_1's multi_logloss: 0.311262\n",
      "[200]\ttraining's multi_logloss: 0.0704913\tvalid_1's multi_logloss: 0.259666\n",
      "[300]\ttraining's multi_logloss: 0.0258234\tvalid_1's multi_logloss: 0.288614\n",
      "[400]\ttraining's multi_logloss: 0.00999505\tvalid_1's multi_logloss: 0.343779\n",
      "[500]\ttraining's multi_logloss: 0.00424382\tvalid_1's multi_logloss: 0.404859\n",
      "[600]\ttraining's multi_logloss: 0.00209117\tvalid_1's multi_logloss: 0.468051\n",
      "Early stopping, best iteration is:\n",
      "[196]\ttraining's multi_logloss: 0.0734444\tvalid_1's multi_logloss: 0.259595\n",
      "fold n°2\n",
      "[LightGBM] [Warning] min_data_in_leaf is set=1, min_child_samples=1 will be ignored. Current value: min_data_in_leaf=1\n",
      "Training until validation scores don't improve for 500 rounds\n",
      "[100]\ttraining's multi_logloss: 0.203916\tvalid_1's multi_logloss: 0.218222\n",
      "[200]\ttraining's multi_logloss: 0.0713725\tvalid_1's multi_logloss: 0.0951717\n",
      "[300]\ttraining's multi_logloss: 0.0265121\tvalid_1's multi_logloss: 0.0564422\n",
      "[400]\ttraining's multi_logloss: 0.0104531\tvalid_1's multi_logloss: 0.0448131\n",
      "[500]\ttraining's multi_logloss: 0.00463044\tvalid_1's multi_logloss: 0.041351\n",
      "[600]\ttraining's multi_logloss: 0.00249505\tvalid_1's multi_logloss: 0.0403509\n",
      "[700]\ttraining's multi_logloss: 0.00153533\tvalid_1's multi_logloss: 0.0426565\n",
      "[800]\ttraining's multi_logloss: 0.000992412\tvalid_1's multi_logloss: 0.0441265\n",
      "[900]\ttraining's multi_logloss: 0.000762428\tvalid_1's multi_logloss: 0.0460495\n",
      "[1000]\ttraining's multi_logloss: 0.000644249\tvalid_1's multi_logloss: 0.0480099\n",
      "Did not meet early stopping. Best iteration is:\n",
      "[1000]\ttraining's multi_logloss: 0.000644249\tvalid_1's multi_logloss: 0.0480099\n",
      "fold n°3\n",
      "[LightGBM] [Warning] min_data_in_leaf is set=1, min_child_samples=1 will be ignored. Current value: min_data_in_leaf=1\n",
      "Training until validation scores don't improve for 500 rounds\n",
      "[100]\ttraining's multi_logloss: 0.203809\tvalid_1's multi_logloss: 0.315355\n",
      "[200]\ttraining's multi_logloss: 0.0710328\tvalid_1's multi_logloss: 0.266697\n",
      "[300]\ttraining's multi_logloss: 0.0262614\tvalid_1's multi_logloss: 0.295481\n",
      "[400]\ttraining's multi_logloss: 0.010349\tvalid_1's multi_logloss: 0.349304\n",
      "[500]\ttraining's multi_logloss: 0.00461055\tvalid_1's multi_logloss: 0.412707\n",
      "[600]\ttraining's multi_logloss: 0.00240066\tvalid_1's multi_logloss: 0.478425\n",
      "Early stopping, best iteration is:\n",
      "[191]\ttraining's multi_logloss: 0.0778846\tvalid_1's multi_logloss: 0.266408\n",
      "fold n°4\n",
      "[LightGBM] [Warning] min_data_in_leaf is set=1, min_child_samples=1 will be ignored. Current value: min_data_in_leaf=1\n",
      "Training until validation scores don't improve for 500 rounds\n",
      "[100]\ttraining's multi_logloss: 0.203802\tvalid_1's multi_logloss: 0.206235\n",
      "[200]\ttraining's multi_logloss: 0.0711267\tvalid_1's multi_logloss: 0.0750674\n",
      "[300]\ttraining's multi_logloss: 0.0264075\tvalid_1's multi_logloss: 0.030998\n",
      "[400]\ttraining's multi_logloss: 0.0103601\tvalid_1's multi_logloss: 0.0153662\n",
      "[500]\ttraining's multi_logloss: 0.00451542\tvalid_1's multi_logloss: 0.009032\n",
      "[600]\ttraining's multi_logloss: 0.00236554\tvalid_1's multi_logloss: 0.00651783\n",
      "[700]\ttraining's multi_logloss: 0.00145281\tvalid_1's multi_logloss: 0.00531193\n",
      "[800]\ttraining's multi_logloss: 0.000961823\tvalid_1's multi_logloss: 0.00429975\n",
      "[900]\ttraining's multi_logloss: 0.000736786\tvalid_1's multi_logloss: 0.00388718\n",
      "[1000]\ttraining's multi_logloss: 0.000619304\tvalid_1's multi_logloss: 0.00364733\n",
      "Did not meet early stopping. Best iteration is:\n",
      "[1000]\ttraining's multi_logloss: 0.000619304\tvalid_1's multi_logloss: 0.00364733\n",
      "fold n°5\n",
      "[LightGBM] [Warning] min_data_in_leaf is set=1, min_child_samples=1 will be ignored. Current value: min_data_in_leaf=1\n",
      "Training until validation scores don't improve for 500 rounds\n",
      "[100]\ttraining's multi_logloss: 0.203376\tvalid_1's multi_logloss: 0.204738\n",
      "[200]\ttraining's multi_logloss: 0.0707119\tvalid_1's multi_logloss: 0.0727307\n",
      "[300]\ttraining's multi_logloss: 0.0261134\tvalid_1's multi_logloss: 0.0285806\n",
      "[400]\ttraining's multi_logloss: 0.010201\tvalid_1's multi_logloss: 0.0127659\n",
      "[500]\ttraining's multi_logloss: 0.00445026\tvalid_1's multi_logloss: 0.00704793\n",
      "[600]\ttraining's multi_logloss: 0.00220567\tvalid_1's multi_logloss: 0.00495291\n",
      "[700]\ttraining's multi_logloss: 0.00130663\tvalid_1's multi_logloss: 0.00421289\n",
      "[800]\ttraining's multi_logloss: 0.000853958\tvalid_1's multi_logloss: 0.00354628\n",
      "[900]\ttraining's multi_logloss: 0.000648649\tvalid_1's multi_logloss: 0.00326843\n",
      "[1000]\ttraining's multi_logloss: 0.000546745\tvalid_1's multi_logloss: 0.00309805\n",
      "Did not meet early stopping. Best iteration is:\n",
      "[1000]\ttraining's multi_logloss: 0.000546745\tvalid_1's multi_logloss: 0.00309805\n"
     ]
    }
   ],
   "source": [
    "##应用五折交叉提高模型稳定性\n",
    "evals_result = {}\n",
    "folds = StratifiedKFold(n_splits=5, shuffle=True, random_state=2022)\n",
    "oof = np.zeros([len(X_train),2])\n",
    "predictions = np.zeros([len(X_test),2])\n",
    "for fold_, (trn_idx, val_idx) in enumerate(folds.split(X_train, y_train)):\n",
    "    print(\"fold n°{}\".format(fold_+1))\n",
    "    #由k折交叉验证划分出来的训练集索引trn_idx和验证集索引val_idx定位到数据 并 对其归一化\n",
    "    x_train = scale.fit_transform(X_train.iloc[trn_idx])\n",
    "    x_val = scale.fit_transform(X_train.iloc[val_idx])\n",
    "    \n",
    "    #与对应的y标签拼接得到完整的从k折交叉验证中划分出来的训练集和验证集\n",
    "    trn_data = lgb.Dataset(x_train, y_train.iloc[trn_idx])\n",
    "    val_data = lgb.Dataset(x_val, y_train.iloc[val_idx])\n",
    "\n",
    "    #最大迭代数\n",
    "    num_round = 1000\n",
    "    #用得到的数据训练模型\n",
    "    clf = lgb.train(params, \n",
    "                    trn_data, \n",
    "                    num_round, \n",
    "                    valid_sets = [trn_data, val_data], \n",
    "                    evals_result = evals_result,   #存放评估结果，即每次迭代的损失函数值\n",
    "                    verbose_eval = 100,   #表示每间隔100次迭代就输出一次信息 \n",
    "                    early_stopping_rounds = 500) #指定迭代多少次没有得到优化则停止训练\n",
    "    x_test = scale.fit_transform(X_test)\n",
    "    #模型预测\n",
    "    #用具有最佳损失函数的那次模型来对对验证集做预测\n",
    "    oof[val_idx] = clf.predict(X_train.iloc[val_idx], num_iteration=clf.best_iteration)    \n",
    "    #用具有最佳损失函数的那次模型来对测试集做预测   predictions存放的两列值是测试集上属于0类和1类的概率\n",
    "    predictions += clf.predict(x_test, num_iteration=clf.best_iteration) / folds.n_splits"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d4097d89",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
